﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO; // FNFException
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace LANmine
{
    public partial class MainForm : Form
    {
        // Create Class Variables for every screen
        Form frmHome;
        Form frmCatering;
        Form frmCompos;
        Form frmPickups;
        Form frmSeats;
        Form frmProfile;
        Form frmCheckin;
        Form frmAdmin;

        // Holds the user profile
        private User lmUser;

        // Language object
        private Language lmLang;

        /// <summary>
        /// Default constructor
        /// </summary>
        public MainForm()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Custom constructor
        /// Application will exit if the required language resource is not found
        /// </summary>
        /// <param name="lmUser">User object to retrieve from the Login form</param>
        public MainForm(User lmUser)
            : this()
        {
            // Save the user object
            this.lmUser = lmUser;
            
            // Create an instance of the Language handler, but make sure the corresponding .resx file exists.
            // Application will force close if this is not the case.
            try
            {
                // Spawn the language handler with the appropriate language
                lmLang = new Language(lmUser.Language);
            }
            catch (FileNotFoundException)
            {
                // Show a detailed dialog box
                MessageBox.Show("A required language resource file was not found. LANmine will now exit.",
                    "Resource file not found!",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Exclamation,
                    MessageBoxDefaultButton.Button1);

                // Exit the application, cannot continue
                this.DialogResult = DialogResult.OK;
            }

            // Spawn subforms    
            SpawnForms();
            // Apply language strings
            ApplyLanguage();
            // Update credits in the Menu Bar
            UpdateCredits();
            // Create registry keys if need be
            CheckRegistry();
        }

        #region Language Specifications
        
        /// <summary>
        /// Overwrite all controls' text with the one in the proper language.
        /// </summary>
        private void ApplyLanguage()
        {
            // Menu Bar
            this.btnCatering.Text = this.lmLang.GetString("menu.btnCatering");
            this.btnCompos.Text = this.lmLang.GetString("menu.btnCompos");
            this.btnPickups.Text = this.lmLang.GetString("menu.btnPickups");
            this.btnSeats.Text = this.lmLang.GetString("menu.btnSeats");
            this.btnProfile.Text = this.lmLang.GetString("menu.btnProfile");
            this.btnCheckin.Text = this.lmLang.GetString("menu.btnCheckin");
            this.btnAdmin.Text = this.lmLang.GetString("menu.btnAdmin");
            this.lblCredits.Text = this.lmLang.GetString("menu.lblCredits");
        }
        #endregion

        #region Member Functions

        /// <summary>
        /// Initialize all necessary forms
        /// </summary>
        private void SpawnForms()
        {
            // Home
            this.frmHome = new HomeForm(this.lmLang);
            this.frmHome.MdiParent = this;
            this.frmHome.Text = "Home";
            this.frmHome.Show();

            // Catering
            this.frmCatering = new CateringForm(this.lmLang, this.lmUser, this.lblCredits);
            this.frmCatering.MdiParent = this;
            this.frmCatering.Text = "Catering";
            this.frmCatering.Show();

            // Compos
            this.frmCompos = new ComposForm(this.lmLang, this.lmUser);
            this.frmCompos.MdiParent = this;
            this.frmCompos.Text = "Competitions";
            this.frmCompos.Show();

            // Pickups
            this.frmPickups = new PickupsForm(this.lmLang, this.lmUser);
            this.frmPickups.MdiParent = this;
            this.frmPickups.Text = "Pickups";
            this.frmPickups.Show();

            // Seats
            this.frmSeats = new SeatsForm(this.lmLang);
            this.frmSeats.MdiParent = this;
            this.frmSeats.Text = "Seats";
            this.frmSeats.Show();

            // Profile
            this.frmProfile = new ProfileForm(this.lmLang, this.lmUser);
            this.frmProfile.MdiParent = this;
            this.frmProfile.Text = "Edit Profile";
            this.frmProfile.Show();

            // Admin-Only Forms
            // Query user class to determine whether the user has the right to open these forms or not.
            // If the user is an admin, initialize the forms and enable the buttons
            if (this.lmUser.IsStaff == true)
            {
                // Enable the buttons
                this.btnAdmin.Enabled = true;
                this.btnCheckin.Enabled = true;

                // Check-in booth
                this.frmCheckin = new CheckinForm(this.lmLang);
                this.frmCheckin.MdiParent = this;
                this.frmCheckin.Text = "LANparty Check-in";
                this.frmCheckin.Show();

                // Application administration
                this.frmAdmin = new AdminForm(this.lmLang);
                this.frmAdmin.MdiParent = this;
                this.frmAdmin.Text = "LANparty Administration";
                this.frmAdmin.Show();
            }
        }

        /// <summary>
        /// Switch the active window to the specified target form
        /// </summary>
        /// <param name="TargetForm">Instance of the form to bring to the front</param>
        private void SwitchWindow(Form TargetForm)
        {
            // Display the specified MDI child
            TargetForm.BringToFront();
            TargetForm.Activate(); // Using activate, not show!
        }

        /// <summary>
        /// Update clock visualization
        /// </summary>
        private void UpdateClock()
        {
            this.lblTime.Text = DateTime.Now.ToLongTimeString();
        }

        /// <summary>
        /// Update Menu Bar credits display
        /// </summary>
        private void UpdateCredits()
        {
            // Add the credits to the credits label
            this.lblCredits.Text = lmLang.GetString("menu.lblCredits") + " " + lmUser.Credits.ToString();
        }

        /// <summary>
        /// Check for the existence of registry keys and create them if necessary.
        /// </summary>
        private void CheckRegistry()
        {
            String asmName = Application.ProductName;

            try
            {
                // Open the regKey
                RegistryKey rKey = Registry.CurrentUser.OpenSubKey("Software\\" + asmName);

                // Check if the RegKey exists
                if (rKey == null)
                {
                    // Create Registry Subkey
                    Registry.CurrentUser.CreateSubKey("Software\\" + asmName);

                    // Create standard registry values for the current Assembly Name
                    String regDir = "HKEY_CURRENT_USER\\Software\\" + asmName;

                    Registry.SetValue(regDir, "ChatLines", 100); // Amount of chat log lines to retrieve
                    Registry.SetValue(regDir, "TimeActiveUsers", 5); // Time to fetch active users
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        #endregion

        #region Event Handlers

        private void MainForm_Load(object sender, EventArgs e)
        {
            // Start the clock
            this.tmrClock.Start();
            UpdateClock();

            // Set the username in the header
            this.lblUserName.Text = lmUser.UserName;

            // Display the home form
            SwitchWindow(this.frmHome);
        }

        private void tmrClock_Tick(object sender, EventArgs e)
        {
            // Make time progress :)
            UpdateClock();
        }

        private void btnHome_Click(object sender, EventArgs e)
        {
            SwitchWindow(this.frmHome);
        }

        private void btnCatering_Click(object sender, EventArgs e)
        {
            SwitchWindow(this.frmCatering);
        }

        private void btnCompos_Click(object sender, EventArgs e)
        {
            SwitchWindow(this.frmCompos);
        }

        private void btnPickups_Click(object sender, EventArgs e)
        {
            SwitchWindow(this.frmPickups);
        }

        private void btnSeats_Click(object sender, EventArgs e)
        {
            SwitchWindow(this.frmSeats);
        }

        private void btnProfile_Click(object sender, EventArgs e)
        {
            SwitchWindow(this.frmProfile);
        }

        private void btnCheckin_Click(object sender, EventArgs e)
        {
            SwitchWindow(this.frmCheckin);
        }

        private void btnAdmin_Click(object sender, EventArgs e)
        {
            SwitchWindow(this.frmAdmin);
        }

        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            // Stop the timer
            this.tmrClock.Stop();

            // Exit the application if restart has not been set
            if(this.DialogResult != DialogResult.Retry)
                this.DialogResult = DialogResult.OK;
        }

        private void btnAbout_Click(object sender, EventArgs e)
        {
            // Show form and dispose properly
            using (AboutForm frmAbout = new AboutForm(lmLang))
            {
                frmAbout.Text = Application.ProductName;
                frmAbout.ShowDialog();
            }
        }

        private void btnProperties_Click(object sender, EventArgs e)
        {
            // Show form and dispose properly
            using (PropertiesForm frmProperties = new PropertiesForm(lmLang))
            {
                frmProperties.Text = lmLang.GetString("properties.lblProperties");
                frmProperties.ShowDialog();
            }
        }

        private void btnLogout_Click(object sender, EventArgs e)
        {
            // Restart the application
            this.DialogResult = DialogResult.Retry;
        }

        #endregion
    }        
}